/**
 * regex-workbench: - Copyright (C) 2012 - Marcius da Silva da Fonseca
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 */
package br.msf.netbeans.regexworkbench;

import java.awt.Color;
import java.awt.SystemColor;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import org.openide.util.Exceptions;

/**
 * <p>A pane that contains the one regex test field with a match counter.
 *
 * @author Marcius da Silva da Fonseca (sf.marcius@gmail.com)
 * @version 1.0
 */
public class SamplePane extends javax.swing.JPanel {

    private static final Color NORMAL_BG = SystemColor.text;
    private static final Color HIGHLIGHT_BG = new Color(255, 192, 64);
    private static final Color MATCH_BG = new Color(92, 255, 92);
    private static final Color DONT_MATCH_BG = new Color(255, 156, 156);
    private static final Highlighter.HighlightPainter HIGHLIGHT_PAINTER = new DefaultHighlighter.DefaultHighlightPainter(HIGHLIGHT_BG);

    /** Creates new form SamplePane */
    public SamplePane() {
        initComponents();
    }

    public void addTextKeyListener(java.awt.event.KeyAdapter adapter) {
        text.addKeyListener(adapter);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        scrollPane = new javax.swing.JScrollPane();
        text = new javax.swing.JTextPane();
        nMatches = new javax.swing.JLabel();

        setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SamplePane.class, "SamplePane.border.title"))); // NOI18N

        text.setFont(new java.awt.Font("Lucida Console", 0, 12)); // NOI18N
        scrollPane.setViewportView(text);

        nMatches.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(nMatches, org.openide.util.NbBundle.getMessage(SamplePane.class, "SamplePane.noMatches.text")); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(scrollPane)
            .addGroup(layout.createSequentialGroup()
                .addComponent(nMatches)
                .addGap(0, 316, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(nMatches))
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel nMatches;
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JTextPane text;
    // End of variables declaration//GEN-END:variables

    public void findPattern(final Pattern pattern) {
        try {
            if (pattern == null || text == null || text.getText().isEmpty()) {
                resetHighlight();
                return;
            }
            // we must get the text direct from the document, cause calling JTextPane.getText()
            // new lines (\n) are replaced by (\r\n) on windows, f*cking the highlight.
            int length = text.getDocument().getLength();
            String str = text.getDocument().getText(0, length);
            final Matcher matcher = pattern.matcher(str);
            final List<MatchEntry> occurrences = new ArrayList<MatchEntry>();
            while (matcher.find()) {
                occurrences.add(new MatchEntry(matcher.start(), matcher.end()));
            }
            highlightOccurrences(occurrences);

            nMatches.setText(getBundleString("SamplePane.nMatches.text", occurrences.size()));
        } catch (BadLocationException ex) {
            throw new RuntimeException(ex);
        }
    }

    public void matchPattern(final Pattern pattern) {
        resetHighlight();
        if (pattern == null || text == null || text.getText().isEmpty()) {
            return;
        }
        boolean matches = (pattern.matcher(text.getText()).matches());
        text.setBackground(matches ? MATCH_BG : DONT_MATCH_BG);
        nMatches.setText(getBundleString("SamplePane.nMatches.text", matches ? 1 : 0));
    }

    public void resetHighlight() {
        text.setBackground(NORMAL_BG);
        text.getHighlighter().removeAllHighlights();
        nMatches.setText(getBundleString("SamplePane.nMatches.text", 0));
    }

    public void clear() {
        resetHighlight();
        text.setText("");
    }

    private void highlightOccurrences(List<MatchEntry> occurrences) {
        try {
            for (MatchEntry matchEntry : occurrences) {
                text.getHighlighter().addHighlight(matchEntry.getStart(), matchEntry.getEnd(), HIGHLIGHT_PAINTER);
            }
        } catch (BadLocationException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private String getBundleString(String key, Object... args) {
        if (args != null && args.length > 0) {
            return org.openide.util.NbBundle.getMessage(SamplePane.class, key, args);
        } else {
            return org.openide.util.NbBundle.getMessage(SamplePane.class, key);
        }
    }
}
